package com.geline.web.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.geline.cloud.core.BaseSessionService;
import com.geline.cloud.util.DynamicSqlUtil;
import com.geline.web.annotation.SqlValid;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Map;

public class SqlValidInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            SqlValid[] list = method.getAnnotationsByType(SqlValid.class);
            if(list!=null && list.length > 0){
                for(SqlValid sqlValid : list){
                    handle(sqlValid, request);
                }
            }
        }
        return true;
    }

    private void handle(SqlValid sqlValid, HttpServletRequest request) {
        String sql = sqlValid.countSql();
        if(StrUtil.isBlank(sql)){
            throw new RuntimeException("@SqlValid countSql is blank !");
        }
        String runSql = DynamicSqlUtil.parseSQL(sql, createParaMap(request));
        Long number = getJdbcTemplate().queryForObject(runSql, Long.class);
        if(sqlValid.exists() && number>0){
            throw new RuntimeException(sqlValid.errorMsg());
        }else if(!sqlValid.exists() && number==0){
            throw new RuntimeException(sqlValid.errorMsg());
        }
    }

    protected JdbcTemplate getJdbcTemplate() {
        return SpringUtil.getBean(JdbcTemplate.class);
    }

    protected BaseSessionService getSessionService() {
        return SpringUtil.getBean(BaseSessionService.class);
    }

    protected Map<String, Object> createParaMap(HttpServletRequest request){
        Map<String, Object> example = (Map<String, Object>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
        example.put("sessionUserId", getSessionService().getUserId());
        Serializable tenantId = getSessionService().getTenantId();
        if(tenantId!=null){
            example.put("sessionTenantId", tenantId);
        }
        return example;
    }
}
